package com.smsc.headend.connector.service.protocol.impl;

import cn.hutool.core.date.SystemClock;
import cn.hutool.core.util.HexUtil;
import com.smsc.headend.connector.bo.ConnectionInfo;
import com.smsc.headend.connector.builder.LoggerBuilder;
import com.smsc.headend.connector.netty.NettyConfigHelper;
import com.smsc.headend.connector.service.FeignAssetManagementService;
import com.smsc.headend.connector.service.LogTerminalAccessService;
import com.smsc.headend.connector.service.protocol.AnsiPacketCodecService;
import com.smsc.headend.connector.utils.LogFileNameUtil;
import com.smsc.headend.module.asset.entity.ComEntity;
import com.smsc.headend.module.protocol.ansi.AnsiTranslator;
import com.smsc.headend.module.protocol.ansi.enums.AnsiSecurityMode;
import com.smsc.headend.module.protocol.ansi.objects.Acse;
import com.smsc.headend.module.protocol.ansi.utils.AnsiBaseUtil;
import com.smsc.headend.module.protocol.cosem.util.ByteUtils;
import com.smsc.headend.module.request.entity.LogComAccess;
import com.smsc.headend.module.task.dto.ConnectorTask;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.util.concurrent.ThreadPoolExecutor;

@Service
@Slf4j
public class AnsiPacketCodecServiceImpl implements AnsiPacketCodecService {
    @Autowired
    LogTerminalAccessService logTerminalAccessService;
    @Autowired
    FeignAssetManagementService assetManagementService;
    @Autowired
    LogFileNameUtil logFileNameUtil;

    @Autowired
    @Qualifier("savePacketPool")
    ThreadPoolExecutor savePool;

    @Override
    public void sendPacket(ConnectorTask connectorTask, Channel channel) {
        channel.attr(NettyConfigHelper.connectTaskRegular).set(connectorTask);
        byte[] packetByte = connectorTask.getPacketBytes()[0];
        ConnectionInfo connectionInfo = buildConnectInfo(connectorTask);
        logTerminalAccessService.savePacket(connectionInfo, SystemClock.now(), packetByte, Boolean.TRUE);
        channel.writeAndFlush(packetByte);
    }

    public ConnectionInfo buildConnectInfo(ConnectorTask connectorTask) {
        ConnectionInfo connectionInfo = new ConnectionInfo();
        connectionInfo.setReturnPacket(connectorTask.getReturnPacket());
        connectionInfo.setComId(connectorTask.getTerminalId());
        connectionInfo.setMeterId(connectorTask.getMeterId());
        connectionInfo.setTaskNo(connectorTask.getTaskNo());
        return connectionInfo;
    }

    @Override
    public Boolean isHeartbeat(byte[] result) {
        String hexResult = HexUtil.decodeHexStr(ByteUtils.byteToHexString(result).replace(" ", ""));
        if (hexResult.contains(DLMSPacketCodecServiceImpl.DHB) || hexResult.contains(DLMSPacketCodecServiceImpl.DRLI)) {
            // Nesco GPRS 表 心跳报文
            return true;
        }
        return false;
    }

    @Override
    public byte[] heartbeatResponse(ComEntity comEntity, byte[] result) {
        if (comEntity.getComId() > 0) {
            ComEntity com = assetManagementService.getComById(comEntity.getComId());
            if (com.getComStatus() == ComEntity.CommunicationStatus.OFFLINE.getCode()) {
                LoggerBuilder.getLogger(logFileNameUtil.getLogFileName(comEntity), this.getClass()).info("Com heartbeat exists but status offline: {} ", comEntity.getComId());
//                logTerminalAccessService.addAccessLog(comEntity.getComId(), LogComAccess.AccessType.connect.getType());
            }
        }
        return new byte[0];
    }
}
